
/**
 *
 *
 * @export
 * @class Utility
 */
export default class Utility {
  static __Instance;

  constructor() {
    this._TempSaveContent = {};
    this.__ConstPrefix = "WeiXinOB";
  }

//   static Cfg = cfg;

  /**
   * 实例
   * @returns {*}
   */
  static instance() {
    if (this.__Instance === null || typeof this.__Instance === "undefined") {
      this.__Instance = new this();
    }
    return this.__Instance;
  }

  /**
   * 日志打印
   *
   * @static
   * @memberof Utility
   */
  static $log() {
    try {
      let __callmethod = "";
      try {
        throw new Error();
      } catch (ex) {
        __callmethod = ex.stack
          .replace(/Error\n/)
          .split(/\n/)[1]
          .replace(/^\s+|\s+$/, "");
      }

      console.log(...arguments);
    } catch (ex) {
      console.log(ex && ex.message ? ex.message : ex);
    }
  }

  /**
   * 常量
   * @type {{SaveUrlPath: string}}
   */
  static constItem = {
    PageSize: 15, //                                                          每页大小数据
    CaptchaTimeout: 60, //
    KeyLanguageHelper: "KLH_OB", //                                           语言名的引用。
    KeyHistory: "KEY_HISTORY", // router
    KeyDispatch: "KEY_DISPATCH", //                                           dispatch
    KeyRouter: "KEY_Router", //                                               Router
    KeyUserInfo: "OB_U", //                                                   用户信息
    KeyToken: "OB_T", //                                                      token
    KeyCurrentSelectGoods: "OB_CURRENT_SELECT_GOODS", //                      当道选中的商品
    KeyCurrentLanguage: "OB_CURRENT_LANGUAGE", //                             当前语言
    KeyCurrentLanguageData: "OB_CURRENT_LANGUAGE_V", //                       保存当前语言的KEY
    KeyCurrentCurrency: "OB_CURRENT_CURRENCY", //                             当前货币
    KeyUrlMap: "OB_URL_MAP", //                                               地址Map
    KeySearchLanguage: 'OB_SEARCH_LANGUAGE', //                               当前搜索使用的语言
    PageData: {
      WaybillDetail: "OB_PAGEDATA_WAYBILLDETAIL" //                           详情
    },
    /**
     * 当前的上下文
     */
    Context: "OBContext", //                                                  当前页面的Context
    /**
     * 事件
     */
    KeyEvent: "onOBEvent", //                                                 事件。
    Events: {
      onUpdateLanguage: "onOB_UPDATE_LANGUAGE", //                            更新语言
      ShowModel: {
        OnActionSheet: "ON_OB_ShowModel_ActionSheet", //
        OnActionSheetComponent: "ON_OB_ShowModel_ActionSheet_Component", //
        OnLoading: "ON_OB_ShowModel_Loading", //                              加载
        OnAlert: "ON_OB_ShowModel_Alert", //                                  弹出信息
        OnAlertHide: "ON_OB_ShowModel_AlertHide", //                          关闭弹出信息
        OnConfirm: "ON_OB_ShowModel_Confirm", //                              确定--取消
        OnToast: "ON_OB_ShowModel_Toast", //                                  确定--取消
        OnToastHide: "ON_OB_ShowModel_ToastHide", //                          确定--取消
        OnShowDialog: "ON_OB_ShowModel_ShowDialog", //                        打开对话框
        OnShowDialogHide: "ON_OB_ShowModel_ShowDialogHide", //                隐藏对话框
        OnShowDialogClose: "ON_OB_ShowModel_ShowDialogClose", //              关闭对话框
        OnActionSheetHide: "ON_OB_ShowModel_ActionSheetHide", //              关闭
        OnLoadingHide: "ON_OB_ShowModel_LoadingHide",
        OnConfirmHide: "ON_OB_ShowModel_ConfirmHide",
        OnSelectItem: "ON_OB_ShowModel_SelectItem" //                         多选单选
      },
      Navbar: {
        onUpdateTitle: "ON_OB_NAVBAR_UPDATE_TITLE",
        onRight: "ON_OB_NAVBAR_RIGHT",
        onLeft: "ON_OB_NAVBAR_LEFT",
        onModifyTitle: "ON_OB_UPDATE_TITLE"
      }
    }
  };

//   static urlItem = routerMap;

  static findUrlInfo(path) {
    if (!path) {
      return;
    }
    const resultArray = Object.values(this.urlItem || {}).filter(
      a => a.path.toLowerCase() === path.toLowerCase()
    );
    if (this.$isArray(resultArray)) {
      return resultArray[0];
    }
    return this.urlItem.NotFound;
  }

  /**
   * 设置内容,这里主要是用来存放临时数据的。
   * @method _SetContent
   * @param key  键值，用于下次的时候获取内容用的。其实就是 _TempSaveContent的属性名称。
   * @param content 要存储的内容
   * @param isSaveLocalStorage 是否保存到本地存储里面
   * @private
   */
  static $setContent(key, content, isSaveLocalStorage) {
    try {
      const self = this.instance();
      if (isSaveLocalStorage) {
        let __Content = content;
        __Content = JSON.stringify(__Content);
        if (typeof uni !== "undefined") {
          uni.setStorageSync(key, __Content);
        }
      }
      self._TempSaveContent[key] = content;
    } catch (ex) {
      console.log(ex && ex.message ? ex.message : ex);
      debugger;
    }
  }

  /**
   * 删除指定字段值。
   * @method __RemoveContent
   * @param key
   * @return {null}
   * @private
   */
  static $removeContent(key, IsRemoveLocalStorage) {
    try {
      const __self = this.instance();
      if (key === null || typeof key === "undefined") {
        return;
      }
      if (__self._TempSaveContent[key]) {
        delete __self._TempSaveContent[key];
      }

      if (IsRemoveLocalStorage && typeof uni !== "undefined") {
        uni.removeStorageSync(key);
      }
    } catch (ex) {
      this.printLog(ex.toString());
    }
  }

  /**
   * 获取内容，
   * @method _GetContent
   * @param key 健名称。其实就是 _TempSaveContent的属性名称。
   * @return {*} 返回内容
   * @private
   */
  static $getContent(key) {
    try {
      if (!key) {
        return null;
      }
      let __Content = null;
      const __self = this.instance();
      if (__self._TempSaveContent[key]) {
        __Content = __self._TempSaveContent[key];
        return __Content;
      }
      if (typeof uni === "undefined") {
        return null;
      }
      if (__Content === null || typeof __Content === "undefined") {
        const _value = uni.getStorageSync(key);
        if (_value !== null && _value !== "" && typeof _value !== "undefined") {
          const __JSONValue = JSON.parse(_value);
          __self._TempSaveContent[key] = __JSONValue;
          __Content = __self._TempSaveContent[key];
        }
      }

      return __Content;
    } catch (ex) {
      return null;
    }
  }

  /**
   * 清空本地数据
   *
   * @static
   * @memberof Utility
   */
  static $clearStorage() {
    try {

      // const languageKey = Utility.constItem.KeyCurrentLanguageData;
      // const currencyKey = Utility.constItem.KeyCurrentCurrency;
      // const languageCodeKey = Utility.constItem.KeyCurrentLanguage;
      const { KeyCurrentLanguageData: languageKey, KeyCurrentCurrency: currencyKey, KeyCurrentLanguage: languageCodeKey, KeyToken, KeyUserInfo } = Utility.constItem;

      const languageData = Utility.$getContent(languageKey);  //                当前语言不清空
      const languageCodeKeyData = Utility.$getContent(languageCodeKey);  //     当前语言代码不清空。
      const currencyKeyData = Utility.$getContent(currencyKey); //              货币
      uni.clearStorageSync();//                                                 清空所的内部数据。
      Utility.$setContent(languageKey, languageData, true); //                  语言
      Utility.$setContent(languageCodeKey, languageCodeKeyData, true); //       语言代码
      Utility.$setContent(currencyKey, currencyKeyData, true); //               货币
      Utility.$removeContent(KeyToken, true);
      Utility.$removeContent(KeyUserInfo, true);
    } catch (ex) {
      console.log('clear storage :' + ex.message);
    }
  }

  /**
   * 是否是数组
   * @param obj
   * @returns {boolean}
   */
  static $isArray(obj) {
    if (!obj || !obj.length || obj.length === 0) {
      return false;
    }
    return Array.isArray(obj);
  }

  /**
   *是否是布尔值
   *
   * @static
   * @param {*} value
   * @returns
   * @memberof Utility
   */
  static isBoolean(value) {
    return typeof value === "boolean";
  }

  /**
   * 判断是否为空
   * true-为空;false-不为空
   * @param obj
   * @returns {boolean}
   */
  static $isNull(obj) {
    return obj === null;
  }

  /**
   * 是否为空
   *
   * @static
   * @param {any} value
   * @returns
   * @memberof Utility
   */
  static $isEmpty(value) {
    if (value === 0) {
      return true;
    }
    if (value) {
      return true;
    }
    return false;
  }

  /**
   * 是否是url
   *
   * @static
   * @param {*} str
   * @returns
   * @memberof Utility
   */
  static $isURL(str) {
    if (!str) {
      return false;
    }
    // return !!str.match(/(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/g);
    const result = /^(https?:\/\/)([0-9a-z.]+)(:[0-9]+)?([/0-9a-z.]+)?(\?[0-9a-z&=]+)?(#[0-9-a-z]+)?/i.exec(
      str
    );
    if (!result) {
      return false;
    }
    return true;
  }

  static parseUrlInfo(url) {
    return (
      /^(https?:\/\/)([0-9a-z.]+)(:[0-9]+)?([/0-9a-z.]+)?(\?[0-9a-z&=]+)?(#[0-9-a-z]+)?/i.exec(
        url
      ) || []
    );
  }

  /**
   * 获取网站类型
   *
   * @static
   * @param {*} url
   * @returns
   * @memberof Utility
   */
  static GetWebSiteType(url) {
    const arr = /^(https?:\/\/)([0-9a-z.]+)(:[0-9]+)?([/0-9a-z.]+)?(\?[0-9a-z&=]+)?(#[0-9-a-z]+)?/i.exec(
      url
    );
    let tp = "taobao";
    if (!arr) {
      return tp;
    }
    const website = arr[2];
    const wsArr = website.split(".");
    return wsArr.length > 2 ? wsArr[wsArr.length - 2] : tp;
  }

  /**
   * 整形数字: 2=true; '2'=true
   *
   * @static
   * @param {any} value
   * @returns
   * @memberof Utility
   */
  static $isIntNumber(value) {
    if (value === "0" || value === 0) {
      return true;
    }
    const re = /^[1-9]+[0-9]*]*$/;
    return re.test(value);
  }

  static $isDigits(val) {
    const re = /^[0-9]*]*$/;
    return re.test(val);
  }

  /**
   * 正整形数字: 2=true; '2'=false
   *
   * @static
   * @param {any} value
   * @returns
   * @memberof Utility
   */
  static $isInt(value) {
    if (Utility.$isIntNumber(value)) {
      return typeof value === "number";
    }
    return false;
  }

  /**
   * 判断是否是数字, 如：'123.1' 、123.1 都是true
   *
   * @static
   * @param {any} value
   * @returns
   * @memberof Utility
   */
  static $isNumber(value) {
    const re = /^[0-9]+\.?[0-9]*$/; // ;
    return re.test(value);
  }

  /**
   * 是不是浮点型, 如：'123.1' = false 、123.1 = true
   *
   * @static
   * @param {any} value
   * @returns
   * @memberof Utility
   */
  static $isFloat(value) {
    const result = Utility.$isNumber(value);
    return result && parseFloat(value) === value;
  }


  /**
   * 对Date的扩展，将 Date 转化为指定格式的String
   * 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
   * 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
   * @method __FormatDate
   * @param fmt
   * @param date
   * @return {*}
   * @example
   *  Utility.FormatDate('yyyy-MM-dd hh:mm:ss.S',new Date());
   * @constructor
   */
  static $formatDate(date, fmt = "yyyy-MM-dd hh:mm:ss.S") {
    if (!date) {
      return "";
    }
    let __this = new Date();
    let _fmt = fmt || "yyyy-MM-dd HH:mm:ss.S";
    if (date !== null) {
      if (Date.parse(date)) {
        __this = date;
      } else {
        try {
          __this = new Date(date);
        } catch (ex) {
          __this = new Date();
        }
      }
    }
    const oo = {
      "M+": __this.getMonth() + 1, // 月份
      "d+": __this.getDate(), // 日
      "D+": __this.getDate(), // 日
      "H+": __this.getHours(), // 小时
      "h+": __this.getHours(), // 小时
      "m+": __this.getMinutes(), // 分
      "s+": __this.getSeconds(), // 秒
      "q+": Math.floor((__this.getMonth() + 3) / 3), // 季度
      S: __this.getMilliseconds() // 毫秒
    };
    if (/(y+)/.test(_fmt)) {
      const fmt1 = _fmt.replace(
        RegExp.$1,
        (__this.getFullYear() + "").substr(4 - RegExp.$1.length)
      );
      _fmt = fmt1;
    }
    for (const kk in oo) {
      if (new RegExp("(" + kk + ")").test(fmt)) {
        _fmt = _fmt.replace(
          RegExp.$1,
          RegExp.$1.length === 1
            ? oo[kk]
            : ("00" + oo[kk]).substr(("" + oo[kk]).length)
        );
      }
    }
    return _fmt;
  }

  /**
   * 判断是否是函数
   * @param func 判断函数对象
   * @returns {boolean} true:成功，false:失败。
   */
  static $isFunction(func) {
    if (
      func !== null &&
      typeof func !== "undefined" &&
      func.constructor.name === "Function"
    ) {
      return true;
    }
    return false;
  }

  /**
   * 判断是否未定义
   * @param obj 判断对象
   * @returns {boolean} true:成功，false:失败。
   */
  static $isUndefined(obj) {
    if (typeof obj === "undefined") {
      return true;
    }
    return false;
  }

  /**
   * 判断是否定义。
   * @param obj 判断对象
   * @return {boolean} true:成功，false:失败。
   */
  static $isDefined(obj) {
    if (typeof obj !== "undefined") {
      return true;
    }
    return false;
  }

  /**
   * 判断是否是日期类型
   *
   * @static    * @param {any} obj  判断对象
   * @returns {boolean} true: 是日期，false:不是日期。
   * @example
   *        Utility.isDate('abcadfa')  ---> false
   *        Utility.isDate(new Date()) ---> true
   *        Utility.isDate('2013年10月10日') ---> true
   * @memberOf Utility
   */
  static $isDate(obj) {
    if (typeof obj === "undefined" || obj === null || obj === "") {
      // 判断是不是 undefined,或 null
      return false;
    }
    const __isDate = obj.constructor.name === "Date"; // 如果传入的就是日期
    if (__isDate) {
      return true;
    }
    try {
      return (
        new Date(
          obj
            .replace("年", "-")
            .replace("月", "-")
            .replace("日", "")
        ).constructor.name === "Date"
      );
    } catch (ex) {
      return false;
    }
  }

  /**
   * 手机号验证
   *
   * @static
   * @param {*} value
   * @returns
   * @memberof Utility
   */
  static $isMobilePhone(value) {
    const reg = /^(\+?0?86\-?)?1[3456789]\d{9}$/;
    return reg.test(value);
  }

  /**
   * 电子邮件验证
   *
   * @static
   * @param {*} value
   * @returns
   * @memberof Utility
   */
  static $isEmail(value) {
    const reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
    return reg.test(value);
  }

  static $isPassword(value) {
    const reg = /^[\w]{6,16}$/;
    return value && value.trim() ? reg.test(value) : false;
  }

  static $isUsername(value) {
    const reg = /^[\w]{3,12}$/;
    return value && value.trim() ? reg.test(value) : false;
  }

  static $isObject(val) {
    if (typeof val !== "object") {
      return false;
    }

    return Object.keys(val).length > 0;
  }

  /**
   * 此方法特殊方法。obj只能传一个对象。
   *
   * @static
   * @param {any} obj 对象
   * @param {any} value 值
   * @memberof Utility
   */
  static $isObjectValue = obj => value => {
    if (!Utility.$isObject(obj)) {
      return false;
    }

    return Object.values(obj).includes(value);
  };


  /**
   * 格式化
   * @example
   * format('{0} is dead, but {1} is alive! {0} {2}', 'ASP', 'ASP.NET');
   * ASP is dead, but ASP.NET is alive! ASP {2}
   * @param format
   * @returns {*}
   */
  static $format(format) {
    const args = Array.prototype.slice.call(arguments, 1);
    return format.replace(/{(\d+)}/g, (match, number) => {
      return typeof args[number] !== "undefined" ? args[number] : match;
    });
  }

  /**
   * 克隆
   *
   * @static
   * @param {*} [obj={}]
   * @returns
   * @memberof Wrapper
   */
  static $clone(obj = {}) {
    return JSON.parse(JSON.stringify(obj));
  }

  static $emit(funName, options) {
    const event = this.$getContent(this.constItem.KeyEvent);
    if (!event) {
      return;
    }
    event.emit(funName, options);
  }

  static $on(funName, callback) {
    const event = this.$getContent(this.constItem.KeyEvent);
    if (!event) {
      return;
    }
    event.on(funName, callback);
  }

  /**
   * 删除事件
   *
   * @static
   * @param {*} funcName
   * @returns
   * @memberof Utility
   */
  static $removeEvent(funcName) {
    const event = this.$getContent(this.constItem.KeyEvent);
    if (!event) {
      return;
    }
    event.removeAllListeners(funcName);
  }

  static $__ToPage(name, params, type = 'push', ) {
    const history = this.$getContent(this.constItem.KeyHistory);
    if (!history || !name) {
      return;
    }
    const query = Object.assign({}, params, { _ts: new Date().getTime() });

    const toPage = (row) => {
      const { path, aliasPath, tabIndex } = row || {};
      const newPath = uni.__PLATFROM__ === 'H5' ? (aliasPath || path) : path;
      if (tabIndex > 0) {
        history.pushTab({ path: newPath, params: query, query });
      } else {
        history[type]({ path: newPath, params: query, query });
      }
    }

    if (typeof name === 'object') {
      toPage(name);
      return;
    }
    if (Object.values(this.urlItem[name] || {}).length > 0) {
      toPage(this.urlItem[name]);
      return;
    }
    const { path, aliasPath } = this.urlItem.NotFound;
    history[type]({ path: aliasPath || path, params: query, query });
  }

  /**
   * 页面跳转
   *
   * @static
   * @param {*} urlInfo
   * @param {*} params
   * @returns
   * @memberof Utility
   */
  static $toPage(name, params) {
    Utility.$__ToPage(name, params, 'push');
  }

  static $toPageReplce(name, params) {
    Utility.$__ToPage(name, params, 'replace');
  }

  static toLogin() {
    Utility.$toPage(Utility.urlItem.Login);
  }

  /**
   * 后退操作
   *
   * @static
   * @param {*} times
   * @returns
   * @memberof Utility
   */
  static $goBack(times) {
    uni.navigateBack({ delta: 1 });
  }

  /**
   * 获取 store 里的数据
   *
   * @static
   * @param {*} stateName
   * @returns
   * @memberof Utility
   */
  static $getStoreValue(stateName) {
    const store = this.$getContent(this.constItem.KeyDispatch);
    if (!store) {
      return { msg: "store is undefined" };
    }
    const { state } = store;
    const { Common } = state || {};
    return Common[stateName];
  }

  /**
   * 给store添加数据。
   *
   * @static
   * @param {*} stateName
   * @param {*} newContent
   * @returns
   * @memberof Utility
   */
  static async $setStoreContent(stateName, newContent) {
    const store = this.$getContent(this.constItem.KeyDispatch);
    if (!store) {
      return { msg: "store is undefined" };
    }

    return new Promise((resolve, reject) => {
      store
        .dispatch(`Common/setContent`, { stateName, content: newContent })
        .then(result => {
          resolve(result);
        })
        .catch(err => {
          Utility.$alert({ msg: err.message });
          resolve(null);
        });
    });
  }

  /**
   * 清空数据
   *
   * @static
   * @returns
   * @memberof Utility
   */
  static async $storeClearn() {
    const store = this.$getContent(this.constItem.KeyDispatch);
    if (!store) {
      return { msg: "store is undefined" };
    }

    return new Promise((resolve, reject) => {
      store
        .dispatch(`Common/clearn`, {})
        .then(result => {
          resolve(result);
        })
        .catch(err => {
          Utility.$alert({ msg: err.message });
          resolve(null);
        });
    });
  }

  /**
   * 翻译语言。
   *
   * @static
   * @param {*} field 字段名称
   * @returns
   * @memberof Utility
   */
  static lang(field, pName) {
    try {
      const { KeyLanguageHelper } = Utility.constItem;

      const klh = Utility.$getContent(KeyLanguageHelper);
      if (!klh || typeof klh.lang !== "function") {
        return field;
      }

      return klh.lang(field, pName) || field;
    } catch (ex) {
      console.log(ex && ex.message ? ex.message : ex);
    }
    return field;
  }

  /**
   * http 请求
   *
   * @static
   * @param {*} method
   * @param {*} { url, stateName, params, data }
   * @returns
   * @memberof Utility
   */
  static async $__onHttpRequest(method, { apiInfo, stateName, params, data, headers }) {
    const store = this.$getContent(this.constItem.KeyDispatch);
    if (!store) {
      return { msg: "store is undefined" };
    }
    const methodName = { get: "Get", put: "Put", post: "Post", delete: "Delete" }[method];

    if (!methodName) {
      return { msg: "not found" };
    }
    const { autoAlert } = apiInfo;
    try {

      await Permission.JudgeApi(apiInfo);
      return new Promise((resolve, reject) => {
        store
          .dispatch(`Common/onHttp${methodName}Api`, { apiInfo, stateName, params, data, headers })
          .then(async (result) => {
            // console.log('-----http--return-result----', result);
            const { code, msg } = result || {};
            switch (code) {
              case 0:
                if (autoAlert !== false) {
                  await Utility.$toast(this.lang(msg), 1500);
                }
                reject(msg);
                return;
              case 401:
                await Utility.$toast(this.lang(msg));
                Utility.$storeClearn();
                Utility.$clearStorage();
                Utility.$toPage(Utility.urlItem.Login);
                return;
            }

            resolve(result);
          })
          .catch(async (err) => {
            console.log("utility-->", err);
            Utility.$loadingHide();
            const { code, status, data } = err || {};
            const msgCode = code || status;
            if (msgCode === 401) {
              const { msg } = data || {};
              const tMsg = msg || "请重新登录.";
              await Utility.$toast(this.lang(tMsg));
              Utility.$storeClearn();
              Utility.$clearStorage();
              Utility.$toPage(Utility.urlItem.Login);
              reject(tMsg);
            } else if (msgCode == 500) {
              // 服务器出错了。
              if (autoAlert !== false) {
                const { msg } = data || {};
                const tmpMsg = this.lang(msg || "An error occurred");
                Utility.$alert({ msg: tmpMsg });
                reject(tmpMsg);
              }
            } else if (msgCode === 300) {
              // 验证不通过。
              const { msg } = data || {};
              if (autoAlert !== false) {
                Utility.$alert({ msg: msg });
              }
              reject(msg);
            } else {
              if (apiInfo && apiInfo.url === "/api/other/errorCatch") {
                resolve({});
              } else {
                if (err) {
                  const { message = "未知错误" } = err || {};
                  if (autoAlert !== false) {
                    Utility.$alert({ msg: this.lang(message) });
                  }
                  reject(err);
                } else {
                  reject("unknown error");
                }
              }
            }
          });
      });

    } catch (ex) {
      console.log(ex && ex.message ? ex.message : ex);
      return null;
    }
  }

  /**
   * get 请求
   *
   * @static
   * @param {*} { url, stateName, params }
   * @returns
   * @memberof Utility
   */
  static async $onGetApi({ apiInfo, stateName, params }) {
    return this.$__onHttpRequest("get", { apiInfo, stateName, params });
  }

  /**
   * post 请求
   *
   * @static
   * @param {*} { url, stateName, params, data }
   * @returns
   * @memberof Utility
   */
  static async $onPostApi({ apiInfo, stateName, params, data, headers }) {
    return this.$__onHttpRequest("post", { apiInfo, stateName, params, data, headers });
  }

  /**
   * 获取Token
   *
   * @static
   * @returns
   * @memberof Utility
   */
  static getToken() {
    const token = this.$getContent(this.constItem.KeyToken);
    if (!token || token === "undefined") {
      const { token: uToken } = this.getUserInfo() || {};
      if (uToken) {
        this.setToken(uToken);
        return uToken;
      }
      return "";
    }
    return token;
  }

  /**
   * 设置Token
   *
   * @static
   * @param {*} token
   * @memberof Utility
   */
  static setToken(token) {
    this.$setContent(this.constItem.KeyToken, token, true);
  }

  /**
   * 保存用户信息
   *
   * @static
   * @param {*} uInfo
   * @memberof Utility
   */
  static setUserInfo(uInfo) {
    if (uInfo && !uInfo.balance) {
      uInfo.balance = uInfo.money;
    }
    this.$setContent(this.constItem.KeyUserInfo, uInfo, true);
  }

  /**
   * 获取用户信息
   *
   * @static
   * @returns
   * @memberof Utility
   */
  static getUserInfo() {
    const ui = this.$getContent(this.constItem.KeyUserInfo);
    if (!ui) {
      return {}
    }
    if (!ui.balance) {
      ui.balance = ui.money;
    }
    return ui;
  }

  /**
   * 是否登录
   *
   * @static
   * @returns
   * @memberof Utility
   */
  static isLogin() {
    const token = this.getToken();
    if (token) {
      return true;
    }

    const userInfo = this.getUserInfo();
    const { token: uToken } = userInfo || {};
    if (!uToken) {
      return false;
    }
    this.setToken(uToken);
    return true;
  }

  /**
   * 延时处理
   *
   * @static
   * @param {number} [delay=1] 延时几秒
   * @returns
   * @memberof Utility
   */
  static async $delay(delay = 1) {
    return await new Promise(resolve => {
      setTimeout(() => {
        resolve();
      }, delay * 1000);
    });
  }

  /**
   *
   *
   * @static
   * @param {*} { msg, title = '提示' }
   * @example
   *   Utility.$alert({ msg: "用户名不能为空" });
   * @memberof Utility
   */
  static $alert({ msg, title = 'Tips', onOk, okTitle }) {

    const opt = { title: this.lang(title, true), content: msg, showCancel: false };
    // if (okTitle) {
    // }
    let confirmText = '';
    try {
      confirmText = Utility.lang(okTitle || 'confirmTitle');
    } catch (ex) {
      console.log(ex);
    }
    console.log('confirmText:', confirmText);
    if (confirmText) {
      // https://uniapp.dcloud.io/api/ui/prompt?id=showmodal
      opt.confirmText = confirmText;
      // #ifndef H5
      opt.confirmText = confirmText.substring(0, 4);
      // #endif
    }

    uni.showModal({
      ...opt,
      success: function (res) {
        if (res.confirm) {
          if (onOk) {
            onOk(res);
          }
        } else if (res.cancel) {
          if (onCancel) {
            onCancel(res);
          }
        }
      }
    });
  }

  static $alertHide(index = 0) {
    this.$emit(this.constItem.Events.ShowModel.OnAlertHide, index);
  }

  /**
   *
   *
   * @static
   * @param {*} { msg, title, onOk }
   * @example
   *   Utility.$confirm({msg: "弹出消息",title: "测试Confirm", onOk: () => console.log("--ok--")});
   * @memberof Utility
   */
  static $confirm({ msg, title = 'tips', onOk, onCancel, okTitle, cancelTitle }) {
    const opt = { title: this.lang(title, true), content: msg };
    if (okTitle) {
      opt.confirmText = okTitle;
    }
    if (cancelTitle) {
      opt.cancelText = cancelTitle;
    }

    uni.showModal({
      ...opt,
      success: function (res) {
        if (res.confirm) {
          if (onOk) {
            onOk(res);
          }
        } else if (res.cancel) {
          if (onCancel) {
            onCancel(res);
          }
        }
      }
    });
  }

  /**
   *
   *
   * @static
   * @param {*} title 弹出内容
   * @param {number} [delayed=1000] 时间 毫秒。
   * @exports
   *   Utility.$toast("哈哈");
   *   Utility.$toast("哈哈",2000);
   * @memberof Utility
   */
  static async $toast(title, delayed = 1000) {
    return new Promise((resolve, reject) => {
      uni.showToast({ title, duration: delayed + 500, icon: 'none' });
      setTimeout(() => {
        resolve('ok');
      }, delayed + 300)
    })
  }

  /**
   * 打开加载
   *
   * @static
   * @memberof Utility
   */
  static $loading() {
    const LanguageHelper = Utility.$getContent(Utility.constItem.KeyLanguageHelper);
    let title = 'Loading';
    if (LanguageHelper) {
      title = LanguageHelper.lang(title, true)
    }
    uni.showLoading({ title });
  }
  /**
   * 关闭加载
   *
   * @static
   * @memberof Utility
   */
  static $loadingHide() {
    uni.hideLoading();
  }

  /**
   * 弹出对话框
   *
   * @static
   * @param {Object} options { component:组件, dataSource:传的数组 , onOk:确定 , onCancel: 取消 , onReset: 重置 }
   * @memberof Utility
   */
  static $dialog(options) {
    this.$emit(this.constItem.Events.ShowModel.OnShowDialog, options);
  }

  static $dialogHide(isInnerClose = true) {
    this.$emit(this.constItem.Events.ShowModel.OnShowDialogHide, {
      isInnerClose
    });
  }


  static $navbarLeftClick(onClick) {
    this.$emit(this.constItem.Events.Navbar.onLeft, { onClick });
  }

  static $navbarRight({ type = "text", value = "edit", onClick }) {
    this.$emit(this.constItem.Events.Navbar.onRight, { type, value, onClick });
  }

  static $navbarRightDefault() {
    this.$navbarRight({ type: "", value: "", onClick: null });
  }

  static $updateNavbarTitle(title) {
    Utility.$emit(Utility.constItem.Events.Navbar.onModifyTitle, title);
  }

  /**
   * 打开一个页签。
   *
   * @static
   * @param {*} url
   * @memberof Utility
   */
  static $openTab(url) {
    let _url = url;
    if (url.indexOf("http://") >= 0 || url.indexOf("https://") >= 0) {
      _url = url;
    } else {
      const { WebSite } = Utility.Cfg;
      _url = `${WebSite}${url}`;
    }

    const win = window.open();
    setTimeout(() => {
      win.location = _url;
    }, 400);
  }

  /**
   * 银行卡，隐藏中间的值。
   *
   * @static
   * @param {*} str
   * @param {number} [begin=4]
   * @param {number} [end=4]
   * @returns
   * @memberof Utility
   */
  static hideStr(str, begin = 4, end = 4) {
    const reg = /^(\d{4})\d+(\d{4})$/;
    // const reg = /^(\d{${begin}})\d+(\d{${end}})$/`;
    let tmp = str.replace(reg, "$1****$2");
    return tmp;
  }

  /**
   * 复制到剪贴板
   *
   * @static
   * @param {*} content
   * @memberof Utility
   */
  static $copyClipboard(content) {

    // #ifndef H5
    uni.setClipboardData({ data: content });
    // #endif

    // #ifdef H5
    const aux = document.createElement("input");
    aux.setAttribute("value", content);
    document.body.appendChild(aux);
    aux.select();
    document.execCommand("copy");
    document.body.removeChild(aux);

    // #endif
  }

  static $Base64ToEncode(str) {
    return Base64Helper.encode(str);

  }

  static $Base64ToDecode(str) {
    return Base64Helper.decode(str);
  }

  static $isWeiXin() {
    if (!navigator) {
      return false;
    }
    var ua = navigator.userAgent.toLowerCase();
    var isWeixin = ua.indexOf("micromessenger") != -1;
    if (isWeixin) {
      return true;
    } else {
      return false;
    }
  }

  static $toFixed(val, num = 2) {
    let _f = "1";
    for (let i = 0; i < num; i += 1) {
      _f += "0";
    }
    const fValue = parseFloat(_f);
    return (Math.round(val * fValue) / fValue).toFixed(num);
  }

  /**
   * 错误信息上报
   *
   * @static
   * @param {*} err
   * @param {*} vm
   * @param {*} info
   * @memberof Utility
   */
  static ErrorReport(err, vm, info) {
    try {
      const md = new MobileDetect(window.navigator.userAgent);
      const a = {
        mobile: md.mobile(),
        phone: md.phone(),
        os: md.os(),
        version: md.versionStr("Build")
      };
      const di = window.DeviceInfo.getDeviceInfo({
        domain: "http://www.1buyo.com"
      });

      const deviceInfo = {
        mobile: `${a.mobile}`,
        deviceModel: a.version,
        version: di.OSVersion,
        os: a.os,
        orientation: di.orientation,
        netWork: di.netWork,
        language: di.language,
        ua: window.navigator.userAgent
      };

      const data = {
        msg: err.message,
        stack: `currRequestUrl:${location.href}      ${err.stack}`,
        deviceInfo
      };
      try {
        const ErrorCatch = {
          url: "/api/other/errorCatch",
          autoAlert: false,
          desc: "错误信息上报",
          data: {
            msg: { require: true, desc: "信息", rules: [{ msg: "不能为空", reg: Utility.$isEmpty }] },
            stack: { require: true, desc: "信息", rules: [{ msg: "不能为空", reg: Utility.$isEmpty }] },
            extend: { require: false, desc: "扩展信息" },
            deviceInfo: { require: true, desc: "设备", default: 1, rules: [{ msg: "不能为空", reg: Utility.$isObject }] }
          }
        };

        Utility.$onPostApi({ apiInfo: ErrorCatch, stateName: "ErrInfo", data });
      } catch (ex) { }
    } catch (ex) { }
  }

  static getCurrentPlatform() {
    return uni.getSystemInfoSync().platform;
  }

  static getClientType() {
    const mapType = {
      android: 'android', ios: 'ios',
      H5: 'h5',
      'MP-WEIXIN': 'miniapp',
      'APP-PLUS-NVUE': 'APP-PLUS-NVUE',
      'APP-PLUS': 'APP-PLUS',
    };
    const platform = this.getCurrentPlatform();
    const _p = uni.__PLATFROM__;
    if (['APP-PLUS-NVUE', 'APP-PLUS'].includes(_p)) {
      return mapType[platform];
    }
    return mapType[_p];
  }
}
